home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / basic / _dlist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  13.1 KB  |  721 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _dlist.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. #include <LEDA/impl/dlist.h>
  17. #include <ctype.h>
  18.  
  19.  
  20. #define SWAP(a,b) { register dlink* x = *a; *a = *b; *b = x; }
  21.  
  22. #define MIN_D 16 
  23.  
  24. //------------------------------------------------------------------------------
  25. // Members of class dlist: base class for all lists
  26. //------------------------------------------------------------------------------
  27.  
  28. dlist::dlist()      
  29. { h=0; 
  30.   t=0;
  31.   count=0;
  32.   iterator=0; 
  33. }
  34.  
  35. dlist::dlist(GenPtr a) 
  36. { h=t=new dlink(a,0,0);
  37.   count=1; 
  38.   iterator=0;  
  39. }
  40.  
  41. dlist::dlist(const dlist& x)
  42. { register dlink* p;
  43.  
  44.   iterator=h=t=0; 
  45.   count = 0; 
  46.                               
  47.   for (p = x.h; p; p = p->succ) append(p->e); 
  48.  
  49.   if (!int_type())
  50.     for (p = h; p; p = p->succ) x.copy_el(p->e);
  51. }
  52.  
  53.  
  54. void dlist::recompute_length() const
  55. { int n = 0;
  56.   for(dlink* it = h; it; it = it->succ)  n++;
  57.   (int&)count = n;
  58. }
  59.  
  60.  
  61. //------------------------------------------------------------------------------
  62. // Iteration:
  63. //------------------------------------------------------------------------------
  64.  
  65. dlink* dlist::move_iterator(int dir) const 
  66. { if (iterator) 
  67.      set_iterator(dir ? iterator->pred : iterator->succ);
  68.   else 
  69.      set_iterator(dir ? t : h);
  70.   return iterator;
  71.  } 
  72.  
  73. bool dlist::current_element(GenPtr& x) const 
  74. { if (iterator) 
  75.   { x = iterator->e; 
  76.     return true; 
  77.    } 
  78.   return false; 
  79.  }
  80.  
  81. bool dlist::next_element(GenPtr& x)    const 
  82. { if (iterator) 
  83.      set_iterator(iterator->succ);
  84.   else 
  85.      set_iterator(h);
  86.  
  87.   if (iterator) 
  88.   { x = iterator->e;
  89.     return true; 
  90.    } 
  91.   return false; 
  92.  }
  93.  
  94. bool dlist::prev_element(GenPtr& x)  const
  95. { if (iterator) 
  96.      set_iterator(iterator->pred);
  97.   else 
  98.      set_iterator(t);
  99.  
  100.   if (iterator) 
  101.   { x = iterator->e;
  102.     return true; 
  103.    } 
  104.   return false; 
  105.  }
  106.  
  107. //------------------------------------------------------------------------------
  108.  
  109. dlink* dlist::get_item(int i) const
  110. { dlink* p = h;
  111.   while ( p && i--) p = p->succ; 
  112.   return p;
  113. }
  114.  
  115. dlink* dlist::succ(dlink* p, int i)  const
  116. { while ( p && i--) p = p->succ; 
  117.   return p;
  118. }
  119.  
  120. dlink* dlist::pred(dlink* p, int i) const
  121. { while ( p && i--) p = p->pred; 
  122.   return p;
  123. }
  124.  
  125. dlink* dlist::search(GenPtr x) const  /* linear search */
  126. { dlink* p = h;
  127.   while ( p && cmp(p->e,x)) p = p->succ; 
  128.   return p;
  129.  
  130. int dlist::rank(GenPtr x)   const   /* rank by linear search */
  131. { dlink* p = h;
  132.   int r = 1;
  133.   while ( p && cmp(p->e,x)) 
  134.   { p = p->succ; 
  135.     r++;
  136.    }
  137.   return (p) ? r : 0;
  138.  
  139. GenPtr dlist::pop()    
  140. { if (h==nil) return nil;
  141.   if (iterator!=0) error_handler(1,"pop: deletion while iterator is active");
  142.   dlink* x=h; 
  143.   h = h->succ;
  144.   if (h) h->pred = 0;
  145.   else t = nil;
  146.   GenPtr p = x->e;
  147.   delete x;
  148.   count--;
  149.   return p;
  150. }
  151.  
  152.  
  153. GenPtr dlist::Pop()    
  154. { if (h==nil) return 0;
  155.   if (iterator!=0) error_handler(1,"Pop: deletion while iterator is active");
  156.   dlink* x=t; 
  157.   t = t->pred;
  158.   if (t) t->succ = 0;
  159.   else h = nil;
  160.   GenPtr p = x->e;
  161.   delete x;
  162.   count--;
  163.   return p;
  164. }
  165.  
  166. dlink* dlist::insert(GenPtr a, dlink* l, int dir) 
  167.   if (iterator!=0) error_handler(2,"insert: insertion while iterator is active");
  168.  
  169.   if (l==0) return dir ? append(a) : push(a); 
  170.  
  171.   dlink* s=l->succ;
  172.   dlink* p=l->pred;
  173.   dlink* n;
  174.   
  175.   if (dir==0) //insert after l
  176.   { n= new dlink(a,l,s);
  177.     l->succ = n;
  178.     if (l==t) t=n;
  179.     else s->pred = n;}
  180.  
  181.   else //insert before l
  182.   { n= new dlink(a,p,l);
  183.     l->pred = n;
  184.     if (l==h) h=n;
  185.     else p->succ = n;}
  186.  
  187.   count++;
  188.  
  189.   return n;
  190. }
  191.  
  192.  
  193. void dlist::conc(dlist& l, int dir)
  194.   if (iterator!=0) error_handler(2,"conc: iterator is active");
  195.  
  196.   if (h==nil)
  197.    { h = l.h; 
  198.      t = l.t; 
  199.     }
  200.   else
  201.   { if (dir==0)  // append l 
  202.     { t->succ = l.h;
  203.       if (l.h) { l.h->pred = t; t = l.t; } 
  204.      }
  205.     else // prepend l
  206.     { h->pred = l.t;
  207.       if (l.t) { l.t->succ= h; h = l.h; } 
  208.      }
  209.    }
  210.  
  211.  count += l.count;
  212.  
  213.  l.h = l.t = 0;
  214.  l.count = 0;
  215. }
  216.  
  217.  
  218. void dlist::split(dlink* p, dlist& l1, dlist& l2, int dir)
  219.    // split L at item p into l1 and l2 and  L is made empty
  220.    // dir = 0: p becomes first item of l2 (l2 empty if p == nil)
  221.    // dir = 1: p becomes last item of l1 (l1 empty if p == nil)
  222.  
  223.    if (iterator!=0) 
  224.    error_handler(1,"list: split while iterator is active");
  225.  
  226.   if (h == 0) error_handler(888,"split on empty list");
  227.  
  228.   l1.clear();
  229.   l2.clear();
  230.  
  231.   if (dir && p) { p = p->succ; dir = 0; }
  232.  
  233.   if (p==nil) 
  234.    { if (dir==0)
  235.       { l2.h = h;
  236.         l2.t = t;
  237.         l2.count = count;
  238.        }
  239.      else
  240.       { l1.h = h;
  241.         l1.t = t;
  242.         l1.count = count;
  243.        }
  244.     }
  245.   else // p != nil
  246.    { if (p->pred)
  247.      { l1.h = h;
  248.        l1.t = p->pred;
  249.        p->pred->succ = 0;
  250.        l1.count = -1;   // do not know length of l1
  251.       }
  252.  
  253.      p->pred = 0;
  254.      l2.h = p;
  255.      l2.t = t;
  256.      l2.count = -1;   // do not know length of l2
  257.     }
  258.  
  259.   // make original list empty
  260.   h = t = 0;
  261.   count = 0;
  262.  
  263. }
  264.  
  265.  
  266.  
  267. GenPtr dlist::del(dlink* it)
  268. { if (iterator) error_handler(1,"dlist: deletion while iterator is active");
  269.   if (it==nil)  error_handler(999,"dlist: delete nil-item");
  270.   if (it==h)  return pop();
  271.   if (it==t)  return Pop();
  272.   dlink*  p = it->pred;
  273.   dlink*  s = it->succ;
  274.   GenPtr x = it->e;
  275.   p->succ = s;
  276.   s->pred = p;
  277.   count--;
  278.   delete it;
  279.   return x;
  280. }
  281.  
  282. dlink* dlist::cyclic_succ(dlink* it) const
  283. { if (it==0) return 0;
  284.   return it->succ? it->succ : h;
  285. }
  286.  
  287. dlink* dlist::cyclic_pred(dlink* it) const
  288. { if (it==0) return 0;
  289.   return it->pred? it->pred : t;
  290. }
  291.  
  292.  
  293. dlink* dlist::max(CMP_PTR f) const
  294. { if (h==0) return 0;
  295.   dlink* m=h;
  296.   dlink* p=m->succ;
  297.  
  298.   if (f) 
  299.      while (p)
  300.      { if (f(p->e,m->e) > 0) m=p;
  301.        p=p->succ;
  302.       }
  303.   else
  304.      while (p)
  305.      { if (cmp(p->e,m->e) > 0) m=p;
  306.        p=p->succ;
  307.       }
  308.  
  309.   return m;
  310. }
  311.  
  312. dlink* dlist::min(CMP_PTR f) const
  313. { if (h==0) return 0;
  314.   dlink* m=h;
  315.   dlink* p=m->succ;
  316.  
  317.   if (f)
  318.      while (p)
  319.      { if (f(p->e,m->e) < 0) m=p;
  320.        p=p->succ;
  321.      }
  322.   else 
  323.      while (p)
  324.      { if (cmp(p->e,m->e) < 0) m=p;
  325.        p=p->succ;
  326.       }
  327.  
  328.   return m;
  329. }
  330.  
  331.  
  332. void dlist::apply(APP_PTR apply)
  333. { register dlink* p = h;
  334.   while (p)
  335.   { apply(p->e);
  336.     p = p->succ;
  337.    }
  338. }
  339.  
  340. void dlist::permute()
  341.   if (iterator!=0) 
  342.           error_handler(3,"permute: modification while iterator is active");
  343.  
  344.   list_item* A = new list_item[count+2];
  345.   list_item x = h;
  346.   int j;
  347.  
  348.   A[0] = A[count+1] = 0;
  349.  
  350.   for(j=1; j <= count; j++)
  351.   { A[j] = x;
  352.     x = x->succ;
  353.    }
  354.  
  355.   for(j=1; j<count; j++)  
  356.   { long r = random(j,count);
  357.     x = A[j];
  358.     A[j] = A[r];
  359.     A[r] = x;
  360.    }
  361.  
  362.   for(j=1; j<=count; j++) 
  363.   { A[j]->succ = A[j+1];
  364.     A[j]->pred = A[j-1];
  365.    }
  366.  
  367.   h = A[1];
  368.   t = A[count];
  369.   
  370.   delete A;
  371. }
  372.         
  373.  
  374. void dlist::bucket_sort(int i, int j, ORD_PTR ord)
  375. { if (iterator!=0) 
  376.         error_handler(3,"bucket_sort: modification while iterator is active");
  377.  
  378.   if (h==nil) return; // empty list
  379.  
  380.   int n = j-i+1;
  381.  
  382.   register list_item* bucket= new list_item[n+1];
  383.   register list_item* stop = bucket + n;
  384.   register list_item* p;
  385.  
  386.   register list_item q;
  387.   register list_item x;
  388.  
  389.   for(p=bucket;p<=stop;p++)  *p = 0;
  390.  
  391.   while (h) 
  392.   { x = h; 
  393.     h = h->succ;
  394.     int k = ord(x->e);
  395.     if (k >= i && k <= j) 
  396.      { p = bucket+k-i;
  397.        x->pred = *p;
  398.        if (*p) (*p)->succ = x;
  399.        *p = x;
  400.       }
  401.     else 
  402.        error_handler(4,"bucket_sort: value out of range") ;
  403.    }
  404.  
  405.  for(p=stop; *p==0; p--); 
  406.  
  407.  // now p points to the end of the rightmost non-empty bucket
  408.  // make it the new head  of the list (remember: list is not empty)
  409.  
  410.  t = *p;
  411.  t->succ = nil;
  412.  
  413.  for(q = *p; q->pred; q = q->pred); // now q points to the start of this bucket
  414.  
  415.  // link buckets together from right to left:
  416.  // q points to the start of the last bucket
  417.  // p points to end of the next bucket
  418.  
  419.  while(--p >= bucket) 
  420.    if (*p)
  421.    { (*p)->succ = q;
  422.      q->pred = *p;
  423.      for(q = *p; q->pred; q = q->pred); 
  424.     }
  425.  
  426.  h = q;   // head = start of leftmost non-empty bucket
  427.  
  428.  delete bucket;
  429. }
  430.  
  431.  
  432. void dlist::quick_sort(dlink** l, dlink** r)
  433. { // use virtual cmp function
  434.  
  435.   register dlink** i = l+(r-l)/2; //random()%(r-l);
  436.   register dlink** k;
  437.  
  438.   if (cmp((*i)->e,(*r)->e)>0) SWAP(i,r);
  439.  
  440.   SWAP(l,i);
  441.  
  442.   GenPtr s = (*l)->e;
  443.  
  444.   i = l;
  445.   k = r;
  446.  
  447.   for(;;)
  448.   { while (cmp((*(++i))->e,s)<0);
  449.     while (cmp((*(--k))->e,s)>0);
  450.     if (i<k) SWAP(i,k) else break;
  451.    }
  452.  
  453.   SWAP(l,k);
  454.  
  455.   if (k > l+MIN_D) quick_sort(l,k-1);
  456.   if (r > k+MIN_D) quick_sort(k+1,r);
  457. }
  458.         
  459. void dlist::quick_sort(dlink** l, dlink** r, CMP_PTR usr_cmp)
  460. { // use parameter usr_cmp
  461.  
  462.   register dlink** i = l+(r-l)/2; //random()%(r-l);
  463.   register dlink** k;
  464.  
  465.   if (usr_cmp((*i)->e,(*r)->e)>0) SWAP(i,r);
  466.  
  467.   SWAP(l,i);
  468.  
  469.   GenPtr s = (*l)->e;
  470.  
  471.   i = l;
  472.   k = r;
  473.  
  474.   for(;;)
  475.   { while (usr_cmp((*(++i))->e,s)<0);
  476.     while (usr_cmp((*(--k))->e,s)>0);
  477.     if (i<k) SWAP(i,k) else break;
  478.    }
  479.  
  480.   SWAP(l,k);
  481.  
  482.   if (k > l+MIN_D) quick_sort(l,k-1,usr_cmp);
  483.   if (r > k+MIN_D) quick_sort(k+1,r,usr_cmp);
  484. }
  485.         
  486.  
  487. void dlist::int_quick_sort(dlink** l, dlink** r)
  488. { // use built-in < and > operators for integers
  489.  
  490.   register dlink** i = l+(r-l)/2; //random()%(r-l);
  491.   register dlink** k;
  492.  
  493.   if ((*i)->e > (*r)->e) SWAP(i,r);
  494.  
  495.   SWAP(l,i);
  496.  
  497.   GenPtr s = (*l)->e;
  498.  
  499.   i = l;
  500.   k = r;
  501.  
  502.   for(;;)
  503.   { while ((*(++i))->e < s);
  504.     while ((*(--k))->e > s);
  505.     if (i<k) SWAP(i,k) else break;
  506.    }
  507.  
  508.   SWAP(l,k);
  509.  
  510.   if (k > l+MIN_D) int_quick_sort(l,k-1);
  511.   if (r > k+MIN_D) int_quick_sort(k+1,r);
  512. }
  513.  
  514.  
  515. void dlist::insertion_sort(dlink** l, dlink** r, dlink** min_stop, 
  516.                                CMP_PTR usr_cmp)
  517. {
  518.   register dlink** min=l;
  519.   register dlink** run;
  520.   register dlink** p;
  521.   register dlink** q;
  522.  
  523.   for (run = l+1; run <= min_stop; run++)
  524.       if (usr_cmp((*run)->e,(*min)->e) < 0) min = run;
  525.  
  526.   SWAP(min,l);
  527.  
  528.   if (r == l+1) return; 
  529.  
  530.   for(run=l+2; run <= r; run++)
  531.   { for (min = run-1; usr_cmp((*run)->e,(*min)->e) < 0; min--);
  532.     min++;
  533.     if (run != min) 
  534.     { dlink* save = *run;
  535.       for(p=run, q = run-1; p > min; p--,q--) *p = *q;
  536.       *min = save;
  537.      }
  538.    }
  539. }
  540.  
  541.  
  542. void dlist::insertion_sort(dlink** l, dlink** r, dlink** min_stop)
  543. {
  544.   register dlink** min=l;
  545.   register dlink** run;
  546.   register dlink** p;
  547.   register dlink** q;
  548.  
  549.   for (run = l+1; run <= min_stop; run++)
  550.       if (cmp((*run)->e,(*min)->e) < 0) min = run;
  551.  
  552.   SWAP(min,l);
  553.  
  554.   if (r == l+1) return; 
  555.  
  556.   for(run=l+2; run <= r; run++)
  557.   { for (min = run-1; cmp((*run)->e,(*min)->e) < 0; min--);
  558.     min++;
  559.     if (run != min) 
  560.     { dlink* save = *run;
  561.       for(p=run, q = run-1; p > min; p--,q--) *p = *q;
  562.       *min = save;
  563.      }
  564.    }
  565. }
  566.  
  567.  
  568. void dlist::int_insertion_sort(dlink** l, dlink** r, dlink** min_stop)
  569. {
  570.   register dlink** min=l;
  571.   register dlink** run;
  572.   register dlink** p;
  573.   register dlink** q;
  574.  
  575.   for (run = l+1; run <= min_stop; run++)
  576.       if ((*run)->e < (*min)->e) min = run;
  577.  
  578.   SWAP(min,l);
  579.  
  580.   if (r == l+1) return; 
  581.  
  582.   for(run=l+2; run <= r; run++)
  583.   { for (min = run-1; (*run)->e < (*min)->e; min--);
  584.     min++;
  585.     if (run != min) 
  586.     { dlink* save = *run;
  587.       for(p=run, q = run-1; p > min; p--,q--) *p = *q;
  588.       *min = save;
  589.      }
  590.    }
  591. }
  592.  
  593.  
  594.  
  595.  
  596. void dlist::sort(CMP_PTR f)
  597. { if (iterator!=0)
  598.       error_handler(1,"sort: modification while iterator is active");
  599.  
  600.   if (count<=1) return;    // nothing to sort
  601.  
  602.   dlink** A = new dlink*[count+2];
  603.  
  604.   register dlink*  loc = h;
  605.   register dlink** p;
  606.   register dlink** stop = A+count+1;
  607.  
  608.   dlink** left  = A+1;
  609.   dlink** right = A+count;
  610.   dlink** min_stop = left + MIN_D;
  611.  
  612.   if (min_stop > right) min_stop = right;
  613.  
  614. min_stop = right;
  615.  
  616.   for(p=A+1; p<stop; p++)
  617.   { *p = loc;
  618.     loc = loc->succ;
  619.    }
  620.  
  621.  
  622.   if (f)
  623.     { quick_sort(left,right,f);
  624.       insertion_sort(left,right,min_stop,f);
  625.      }
  626.   else  
  627.     if (int_type())
  628.       { int_quick_sort(left,right);
  629.         int_insertion_sort(left,right,min_stop);
  630.        }
  631.     else
  632.       { quick_sort(left,right);
  633.         insertion_sort(left,right,min_stop);
  634.        }
  635.  
  636.   *A = *stop = 0;
  637.  
  638.   for (p=A+1;p<stop;p++) 
  639.   { (*p)->succ = *(p+1);
  640.     (*p)->pred = *(p-1);
  641.    }
  642.  
  643.   h = A[1];
  644.   t = A[count];
  645.  
  646.   delete A;
  647. }
  648.  
  649.  
  650. dlist& dlist::operator=(const dlist& x)
  651. { register dlink* p;
  652.  
  653.   clear();
  654.  
  655.   for (p = x.h; p; p = p->succ) append(p->e); 
  656.  
  657.   if (!int_type())
  658.     for (p = h; p; p = p->succ) copy_el(p->e);
  659.                                 
  660.   return *this;
  661. }
  662.  
  663.  
  664. dlist dlist::operator+(const dlist& x)  // concatenation
  665. { dlist y = x;
  666.   dlink* p = t;
  667.   while (p) { y.push(p->e);    
  668.               x.copy_el(p->e);
  669.               p = p->pred;}
  670.   return y;
  671. }
  672.  
  673.  
  674. void dlist::clear()
  675. { if (h==nil) return;
  676.  
  677.   if (!int_type())
  678.     for(dlink* p = h; p; p = p->succ) clear_el(p->e);
  679.  
  680.   deallocate_list(h,t,sizeof(dlink));
  681.   iterator=h=t=nil;
  682.   count=0;
  683. }
  684.  
  685. void dlist::print(ostream& out, string s, char space) const
  686. { list_item l = h;
  687.   cout << s;
  688.   if (l)
  689.   { print_el(l->e,out); 
  690.     l = l->succ;
  691.     while (l)
  692.       { out << string(space);
  693.         print_el(l->e,out); 
  694.         l = l->succ;
  695.        }
  696.   }
  697.   out.flush();
  698. }
  699.  
  700.  
  701. void dlist::read(istream& in, string s, char delim)
  702. { char c;
  703.   GenPtr x;
  704.   cout << s;
  705.   clear();
  706.   for(;;)
  707.   { while (in.get(c) && isspace(c) && c!=delim);
  708.     if (!in || c==delim) break;
  709.     in.putback(c);
  710.     read_el(x,in); 
  711.     append(x);
  712.    }
  713. }
  714.